package com.loveprogrammer.eternity.action;

import com.loveprogrammer.eternity.common.Tuple;
import com.loveprogrammer.eternity.enums.EffectTimeEnum;
import com.loveprogrammer.eternity.model.Character;
import com.loveprogrammer.eternity.model.attack.AttackResult;
import com.loveprogrammer.eternity.model.game.HeroWrapper;
import com.loveprogrammer.eternity.model.game.TaskManager;
import com.loveprogrammer.eternity.model.mission.support.KillMonsterMission;
import com.loveprogrammer.eternity.model.task.TaskDefinition;
import com.loveprogrammer.eternity.notify.Notify;
import com.loveprogrammer.eternity.service.EffectService;
import com.loveprogrammer.eternity.skill.Skill;
import com.loveprogrammer.eternity.skill.State;
import com.loveprogrammer.eternity.skill.support.states.AbstractState;
import com.loveprogrammer.eternity.task.MainTaskService;
import com.loveprogrammer.eternity.task.event.EffectEventListener;
import com.loveprogrammer.eternity.task.event.EventManager;
import com.loveprogrammer.eternity.task.event.MessageEventListener;
import io.netty.util.HashedWheelTimer;

import java.util.Comparator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

/**

 * @version 1.0.0
 * @description: 基础操作类
 * @author: eric
 * @date: 2022-09-16 18:10
 **/
public abstract class BaseAction {

    public static EventManager eventManager;

    public static HashedWheelTimer timer;

    public static Notify notify;

    public static MainTaskService mainTaskService;
    /**
     * 是否更改标志
     */
    private static volatile AtomicBoolean changeFlag=new AtomicBoolean(false);

    static {
        // 任务监听 消息监听
        eventManager = new EventManager(
                EventManager.EventType.TASK,
                EventManager.EventType.Message,
                EventManager.EventType.Effect
        );
//        eventManager.subscribe(EventManager.EventType.MQ, new );
        // 消息监听器
        eventManager.subscribe(EventManager.EventType.Message, new MessageEventListener());
        // 特殊效果监听器
        eventManager.subscribe(EventManager.EventType.Effect, new EffectEventListener());
        // timer = new HashedWheelTimer(5, TimeUnit.SECONDS, 10);
        mainTaskService = new MainTaskService();
        try {
            mainTaskService.init();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

//    public static final Scanner input = new Scanner(System.in);

    public BaseAction(){

    }

    public Character findSingleAttacker(List<? extends Character> defences, boolean taunt) {

        return findSingleAttacker(defences,taunt,false);

    }

    public Character findSingleAttacker(List<? extends Character> defences, boolean taunt,boolean desc) {
        if(defences == null){
            return null;
        }
        // 除了看血量还要看前后排 默认是先前排后后排
        if(desc){
            defences.sort(Comparator.comparing(Character::getPosition).thenComparing(Comparator.comparing(Character::getCurrentHp).reversed()));
        }else {
            defences.sort(Comparator.comparing(Character::getPosition).thenComparing(Character::getCurrentHp));
        }
        // 如果吃嘲讽
        if(taunt){
            for (Character defence : defences) {
                List<State> states = defence.getStates();
                if(states != null && states.size() > 0){
                    for (State state : states) {
                        // 嘲讽状态是8
                        if(state.id() == 8){
                            return defence;
                        }
                    }
                }
            }
        }
        return defences.get(0);
    }

    public AtomicBoolean getChangeFlag() {
        return changeFlag;
    }

    public void setChangeFlag(AtomicBoolean changeFlag) {
        this.changeFlag = changeFlag;
    }

    protected void setTimeTask(AbstractState state, int times){
        if(timer == null) {
            timer = new HashedWheelTimer(100, TimeUnit.MILLISECONDS, 256);
        }
        // 单线程就可以了
        try {
            for (int i = 1; i <= times; i++) {
                if(i == times) {
                    timer.newTimeout(timeout -> {
                        state.run();
                        state.reset();
                    }, i, TimeUnit.SECONDS);
                }else{
                    timer.newTimeout(timeout -> state.run(), i, TimeUnit.SECONDS);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 以下是老的方法
        // 启动一个线程去执行这个方法
//        subFightExecutorService.execute(() -> {
//            state.setNotify(notify);
//            Timer timer = new Timer();
//            timer.schedule(state, 0, 1000);
//            int count = counts;
//            boolean reset = false;
//            while(count > 0){
//                // 死亡后立刻跳出
//                if(state.getCharacter().checkDead()){
//                    reset = true;
//                    break;
//                }
//                // 如果状态被移除也break
//                if(state.getCharacter() == null){
//                    reset = true;
//                    break;
//                }
//                try {
//                    Thread.sleep(1000);
//                    count--;
//                } catch (InterruptedException e) {
//                    // e.printStackTrace();
//                    break;
//                }
//            }
//            timer.cancel();
//            if(!reset) {
//                state.reset();
//            }
//        });
    }

    public Notify getNotify() {
        return notify;
    }

    // 统一暴击检查
    public boolean critCheck(Character character) {
        boolean crit = false;
        int percents = character.getTechnique() * 100 / (Math.abs(character.getTechnique()) + 20000);
        // 暴击几率最大65 如果技巧超过40000 对暴击就无效了，但是装备的暴击率加成还是有效的 但所有的加成不能超过95%
        percents = Math.min(percents,65);
        percents += character.getCriticalStrikeRateAdd();
        if(new Random().nextInt(100) < Math.min(percents,75)){
            crit = true;
        }
        return crit;
    }

    // 统一暴击
    public int critPower(int power){
        return (int) (power * 1.3);
    }

    protected void computeHarm(StringBuilder builder, boolean crit,
                               Character defence, AttackResult harm,
                               Character character,
                               List<? extends Character> attack,
                               List<? extends Character> defences) {
        if(harm.getHarm() > 0) {
            // 要检查被动技能
            List<Skill> passiveSkills = defence.getSkills().stream().filter(e -> e.opportunityPassive() == 2).collect(Collectors.toList());
            for (Skill passiveSkill : passiveSkills) {
                // 被动技能触发 例如闪避 例如硬甲 反弹等等
                Tuple<String, List<Character>> launch = passiveSkill.assembleAttackEntity(harm)
                        .launch(defence, null, null, null);
                if(launch != null && launch.getKey() != null){
                    builder.append(launch.getKey());
                }
            }
            if(harm.getHarm() > 0) {
                builder.append("对").append(defence.getName()).append("造成伤害").append(harm.getHarm()).append("点");
                if (crit) {
                    builder.append("(暴击)");
                }
                defence.hp().addAndGet(-harm.getHarm());
                // 造成了伤害后，通知并触发英雄的特殊效果 例如吸血 撕裂  眩晕 等等
                builder.append(EffectService.notifyEffect(character, EffectTimeEnum.ATTACK_AFTER, harm, attack, defence));
            }
            // TODO 反弹伤害 不好计算
            if(harm.getReboundHarm() > 0){

            }
        }else{
            builder.append(harm.getMessage());
        }
    }

    public void checkTaskForKillMonsters(Character character, HeroWrapper attackHero) {
        // 检查任务
        TaskManager taskManager = attackHero.getTaskManager();
        ConcurrentHashMap<String, TaskDefinition> monsterTasks = taskManager.getKillMonsterTasks();
        // 过滤杀怪任务
        TaskDefinition taskDefinition = monsterTasks.get(String.valueOf(character.getId()));
        if(taskDefinition != null){
            KillMonsterMission mission = (KillMonsterMission)taskDefinition.getMission();
            mission.setProgress(mission.getProgress()+1);
            eventManager.notifyMessage("任务击杀 [" + mission.getProgress() + "/" + mission.getGoal() + "]", 1);
            if(mission.getProgress() >= mission.getGoal()){
                taskManager.complete(taskDefinition,mainTaskService);
            }
        }
    }
}
